package no.cicero.testframework.model.testcase;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ClientObject {
	private final Map<String, Object> fields = new LinkedHashMap<String, Object>();

    public int getFieldsSize(){
        return fields.size();
    }

	public Map<String, Object> getFields() {
		return fields;
	}

	public Object getField(String name) {
		return fields.get(name);
	}

	public Object addField(String name, String value) {
		return doAddField(name, value);
	}

	public Object addField(String name, ClientObject value) {
		return doAddField(name, value);
	}

	private Object doAddField(String name, Object value) {
		Object valueToInsert = value;
        
		if (fields.containsKey(name)) {
			Object current = fields.get(name);

			if (current instanceof List) {
				valueToInsert = current;
			} else {
				valueToInsert = new ArrayList();
				((List) valueToInsert).add(current);
			}

			if (value instanceof List) {
				((List) valueToInsert).addAll((List) value);
			} else {
				((List) valueToInsert).add(value);
			}

		}
		return fields.put(name, valueToInsert);
	}

    @Override
    public boolean equals(Object o) {

        if (this == o) return true;
        if (o == null ) return false;

        if(o instanceof ClientObject){
            ClientObject clientObject = (ClientObject) o;
            if(this.fields.size() > clientObject.getFieldsSize()) return false;
            for(Map.Entry<String, Object> entry: fields.entrySet()) {
                String fieldName = entry.getKey();
                Object v = entry.getValue();
             
                if(v instanceof ClientObject){
                     ClientObject fieldValue = (ClientObject) entry.getValue();
                     if(fieldValue.getFieldsSize() > 0 && !fieldValue.equals(clientObject.getField(fieldName)))
                         return false;
                }else if(v instanceof String){
                    String fieldValue = (String) entry.getValue();
                    if(!fieldValue.equals(clientObject.getField(fieldName)))
                        return false;
                }
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = 0;
        for (Map.Entry<String, Object> entry : fields.entrySet()) {
            if (entry.getValue() instanceof ClientObject) {
                ClientObject fieldValue = (ClientObject) entry.getValue();
                result += (fieldValue != null && fieldValue.getFieldsSize() > 0 ? fieldValue.hashCode() : 0);
            } else if (entry.getValue() instanceof String) {
                String fieldValue = (String) entry.getValue();
                result += (fieldValue != null ? fieldValue.hashCode() : 0);
            }
        }
        return result;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        if (fields.size() > 0) {
            sb.append("{");
            for (Map.Entry<String, Object> entry : fields.entrySet()) {
                sb.append(entry.getKey()).append(" : ");
                if (entry.getValue() instanceof ClientObject) {
                    ClientObject fieldValue = (ClientObject) entry.getValue();
                    if(fieldValue.getFieldsSize() > 0)
                        sb.append(fieldValue.toString());
                } else if (entry.getValue() instanceof String) {
                    String fieldValue = (String) entry.getValue();
                    sb.append(fieldValue);
                }
                sb.append(" <br> ");
            }
            sb.append('}').append("<br>");
        }
        return sb.toString();
    }
}
